﻿using System;
using System.Collections.Specialized;
using System.IO;
using System.Xml.XPath;

using WebDavProcessor.Interfaces;
using WebDavProcessor.Constants;

namespace WebDavProcessor.Methods
{
    /// <summary>
    /// 
    /// </summary>
    public abstract class WebDavMethod
    {
        private string methodName;
        private Uri methodUri;
        private NameValueCollection methodHeaders;
        private Stream methodBody;

        public string MethodName { get { return methodName; } }
        public Uri RequestUri { get { return methodUri; } }
        public NameValueCollection Headers { get { return methodHeaders; } }
        public Stream InputStream { get { return methodBody; } }

        public WebDavMethod(IWebDavRequest webDavRequest)
        {
            if (webDavRequest.RequestUri.IsAbsoluteUri)
            {
                methodUri = new Uri(webDavRequest.RequestUri.PathAndQuery, UriKind.Relative);
            }
            else
            {
                methodUri = webDavRequest.RequestUri;
            }
            methodName = webDavRequest.Method;
            methodHeaders = webDavRequest.Headers;
            methodBody = webDavRequest.InputStream;
        }
        public WebDavMethod(string requestMethod, Uri requestUri, NameValueCollection requestHeaders, Stream requestInputStream)
        {
            if (requestUri.IsAbsoluteUri)
            {
                methodUri = new Uri(requestUri.PathAndQuery, UriKind.Relative);
            }
            else
            {
                methodUri = requestUri;
            }
            methodName = requestMethod;
            methodHeaders = requestHeaders;
            methodBody = requestInputStream;
        }

        /// <summary>
        /// Processes the request and sets general properties to the given response.
        /// </summary>
        /// <param name="webDavResponse">Response that would maintain general properties.</param>
        /// <param name="resourceProvider">Provider to the resource operations.</param>
        public abstract void ProcessRequest(IWebDavResponse webDavResponse, IWebDavResourceProvider resourceProvider);
        /// <summary>
        /// Processes the request and returns simple response.
        /// </summary>
        /// <param name="resourceProvider">Provider to the resource operations.</param>
        /// <returns>WebDavSimpleResponse that maintains general properties.</returns>
        public IWebDavResponse ProcessRequest(IWebDavResourceProvider resourceProvider)
        {
            IWebDavResponse response = new WebDavSimpleResponse(WebDavStatusCodes.OK, WebDavStatusDescriptions.OK);
            this.ProcessRequest(response, resourceProvider);
            return response;
        }

        public static void SetError(IWebDavResponse webDavResponse, int statusCode)
        {
            if (statusCode < 400 || statusCode >= 600)
            {
                statusCode = WebDavStatusCodes.InternalServerError;
            }
            try
            {
                webDavResponse.StatusCode = statusCode;
                webDavResponse.StatusDescription = WebDavStatusDescriptions.GetDescription(statusCode);
            }
            catch (Exception)
            {
                throw new WebDavException(WebDavStatusCodes.InternalServerError);
            }
        }
    }
}
